import tkinter as tk
from tkinter import filedialog, ttk, messagebox
from PIL import Image
import os
import sys

class ImageResizerApp:
    def __init__(self, root):
        self.root = root
        self.root.title("图片尺寸调整工具")
        self.root.geometry("700x600")  # 增大窗口初始尺寸
        self.root.minsize(600, 550)    # 设置最小尺寸
        self.root.resizable(True, True)
        
        # 设置中文字体支持
        self.setup_fonts()
        
        # 输入文件路径
        self.input_path = tk.StringVar()
        
        # 输出文件路径
        self.output_path = tk.StringVar()
        
        # 尺寸设置
        self.width_var = tk.StringVar()
        self.height_var = tk.StringVar()
        
        # 质量设置
        self.quality_var = tk.IntVar(value=85)
        
        # 原始图片信息
        self.original_width = 0
        self.original_height = 0
        
        # 创建界面
        self.create_widgets()
    
    def setup_fonts(self):
        # 确保中文正常显示
        if sys.platform.startswith('win'):
            default_font = ('Microsoft YaHei', 10)
        else:
            default_font = ('SimHei', 10)
            
        self.root.option_add("*Font", default_font)
    
    def create_widgets(self):
        # 创建主框架并添加滚动条支持
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 创建画布和滚动条，支持窗口较小时滚动查看内容
        canvas = tk.Canvas(main_frame)
        scrollbar = ttk.Scrollbar(main_frame, orient="vertical", command=canvas.yview)
        scrollable_frame = ttk.Frame(canvas)
        
        scrollable_frame.bind(
            "<Configure>",
            lambda e: canvas.configure(
                scrollregion=canvas.bbox("all")
            )
        )
        
        canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
        canvas.configure(yscrollcommand=scrollbar.set)
        
        canvas.pack(side="left", fill="both", expand=True)
        scrollbar.pack(side="right", fill="y")
        
        # 内容区域 - 使用滚动框架
        content_frame = scrollable_frame
        content_frame.configure(padding="10")
        
        # 输入文件选择
        ttk.Label(content_frame, text="源图片:").grid(row=0, column=0, sticky=tk.W, pady=5)
        ttk.Entry(content_frame, textvariable=self.input_path, width=50).grid(row=0, column=1, pady=5)
        ttk.Button(content_frame, text="浏览...", command=self.browse_input).grid(row=0, column=2, padx=5, pady=5)
        
        # 输出文件选择
        ttk.Label(content_frame, text="保存到:").grid(row=1, column=0, sticky=tk.W, pady=5)
        ttk.Entry(content_frame, textvariable=self.output_path, width=50).grid(row=1, column=1, pady=5)
        ttk.Button(content_frame, text="浏览...", command=self.browse_output).grid(row=1, column=2, padx=5, pady=5)
        
        # 原始图片信息
        self.original_info_label = ttk.Label(content_frame, text="原始尺寸: -- x --")
        self.original_info_label.grid(row=2, column=0, columnspan=3, sticky=tk.W, pady=5)
        
        # 尺寸设置
        size_frame = ttk.LabelFrame(content_frame, text="目标尺寸 (像素)", padding="10")
        size_frame.grid(row=3, column=0, columnspan=3, sticky=tk.W+tk.E, pady=10)
        
        ttk.Label(size_frame, text="宽度:").grid(row=0, column=0, sticky=tk.W, padx=5, pady=5)
        ttk.Entry(size_frame, textvariable=self.width_var, width=15).grid(row=0, column=1, padx=5, pady=5)
        
        ttk.Label(size_frame, text="高度:").grid(row=0, column=2, sticky=tk.W, padx=5, pady=5)
        ttk.Entry(size_frame, textvariable=self.height_var, width=15).grid(row=0, column=3, padx=5, pady=5)
        
        ttk.Button(size_frame, text="保持比例", command=self.maintain_aspect_ratio).grid(row=0, column=4, padx=10, pady=5)
        
        # 质量设置
        quality_frame = ttk.LabelFrame(content_frame, text="图片质量", padding="10")
        quality_frame.grid(row=4, column=0, columnspan=3, sticky=tk.W+tk.E, pady=10)
        
        ttk.Label(quality_frame, text="质量:").grid(row=0, column=0, sticky=tk.W, padx=5, pady=5)
        quality_scale = ttk.Scale(quality_frame, from_=1, to=100, variable=self.quality_var, 
                                 orient=tk.HORIZONTAL, length=300, command=self.update_quality_label)
        quality_scale.grid(row=0, column=1, padx=10, pady=5)
        
        self.quality_label = ttk.Label(quality_frame, text=f"{self.quality_var.get()}%")
        self.quality_label.grid(row=0, column=2, padx=5, pady=5)
        
        # 操作按钮
        button_frame = ttk.Frame(content_frame)
        button_frame.grid(row=5, column=0, columnspan=3, pady=15)
        
        ttk.Button(button_frame, text="调整大小", command=self.resize_image, width=15).pack(side=tk.LEFT, padx=10)
        ttk.Button(button_frame, text="重置", command=self.reset_fields, width=15).pack(side=tk.LEFT, padx=10)
        ttk.Button(button_frame, text="退出", command=self.root.quit, width=15).pack(side=tk.LEFT, padx=10)
        
        # 状态区域
        self.status_var = tk.StringVar(value="就绪")
        ttk.Label(content_frame, textvariable=self.status_var, foreground="blue").grid(row=6, column=0, columnspan=3, sticky=tk.W, pady=5)
        
        # 结果显示区域 - 增大尺寸以确保内容可见
        ttk.Label(content_frame, text="处理结果:").grid(row=7, column=0, sticky=tk.W, pady=5)
        self.result_text = tk.Text(content_frame, height=8, width=70, state=tk.DISABLED, wrap=tk.WORD)
        self.result_text.grid(row=8, column=0, columnspan=3, pady=10)
        
        # 添加滚动条到结果文本框
        result_scroll = ttk.Scrollbar(content_frame, orient="vertical", command=self.result_text.yview)
        result_scroll.grid(row=8, column=3, sticky="ns")
        self.result_text.configure(yscrollcommand=result_scroll.set)
        
        # 配置列权重，使其可以拉伸
        for i in range(3):
            content_frame.columnconfigure(i, weight=1)
        size_frame.columnconfigure(4, weight=1)
        quality_frame.columnconfigure(1, weight=1)
    
    def update_quality_label(self, value):
        """更新质量标签显示"""
        self.quality_label.config(text=f"{int(float(value))}%")
    
    def browse_input(self):
        """浏览选择输入图片"""
        file_path = filedialog.askopenfilename(
            filetypes=[("图片文件", "*.jpg;*.jpeg;*.png;*.bmp;*.gif;*.tiff")]
        )
        if file_path:
            self.input_path.set(file_path)
            # 自动生成输出路径
            self.generate_output_path()
            # 获取并显示原始图片信息
            self.get_image_info()
    
    def browse_output(self):
        """浏览选择输出路径"""
        # 获取输入文件的扩展名
        input_ext = os.path.splitext(self.input_path.get())[1].lower()
        file_path = filedialog.asksaveasfilename(
            defaultextension=input_ext,
            filetypes=[("JPEG图片", "*.jpg;*.jpeg"), 
                      ("PNG图片", "*.png"),
                      ("所有图片文件", "*.jpg;*.jpeg;*.png;*.bmp;*.gif;*.tiff")]
        )
        if file_path:
            self.output_path.set(file_path)
    
    def generate_output_path(self):
        """自动生成输出路径"""
        input_path = self.input_path.get()
        if not input_path:
            return
            
        dir_name = os.path.dirname(input_path)
        base_name = os.path.basename(input_path)
        name_parts = base_name.split('.')
        
        if len(name_parts) > 1:
            # 有扩展名的情况
            ext = name_parts[-1]
            name = '.'.join(name_parts[:-1])
            output_path = os.path.join(dir_name, f"{name}_resized.{ext}")
        else:
            # 没有扩展名的情况
            output_path = os.path.join(dir_name, f"{base_name}_resized")
            
        self.output_path.set(output_path)
    
    def get_image_info(self):
        """获取图片信息"""
        try:
            with Image.open(self.input_path.get()) as img:
                self.original_width, self.original_height = img.size
                self.original_info_label.config(
                    text=f"原始尺寸: {self.original_width} x {self.original_height} 像素"
                )
        except Exception as e:
            messagebox.showerror("错误", f"无法读取图片信息: {str(e)}")
            self.original_info_label.config(text="原始尺寸: -- x --")
    
    def maintain_aspect_ratio(self):
        """保持宽高比例"""
        if self.original_width == 0 or self.original_height == 0:
            messagebox.showwarning("警告", "请先选择一张图片")
            return
            
        try:
            width_text = self.width_var.get().strip()
            height_text = self.height_var.get().strip()
            
            # 如果宽度和高度都填写了，不做处理
            if width_text and height_text:
                return
                
            # 比例计算
            ratio = self.original_width / self.original_height
            
            # 如果只填写了宽度
            if width_text and not height_text:
                width = int(width_text)
                height = int(width / ratio)
                self.height_var.set(str(height))
            
            # 如果只填写了高度
            if height_text and not width_text:
                height = int(height_text)
                width = int(height * ratio)
                self.width_var.set(str(width))
                
        except ValueError:
            messagebox.showerror("错误", "请输入有效的数字")
    
    def reset_fields(self):
        """重置所有字段"""
        self.input_path.set("")
        self.output_path.set("")
        self.width_var.set("")
        self.height_var.set("")
        self.quality_var.set(85)
        self.original_width = 0
        self.original_height = 0
        self.original_info_label.config(text="原始尺寸: -- x --")
        self.status_var.set("就绪")
        self.result_text.config(state=tk.NORMAL)
        self.result_text.delete(1.0, tk.END)
        self.result_text.config(state=tk.DISABLED)
    
    def resize_image(self):
        """调整图片大小"""
        input_path = self.input_path.get()
        output_path = self.output_path.get()
        
        # 验证输入
        if not input_path:
            messagebox.showerror("错误", "请选择源图片")
            return
            
        if not output_path:
            messagebox.showerror("错误", "请指定保存路径")
            return
            
        # 获取尺寸参数
        try:
            width_text = self.width_var.get().strip()
            height_text = self.height_var.get().strip()
            
            width = int(width_text) if width_text else None
            height = int(height_text) if height_text else None
            
            # 如果都未指定，使用原始尺寸
            if width is None and height is None:
                width, height = self.original_width, self.original_height
                
            # 验证尺寸为正数
            if width is not None and width <= 0:
                messagebox.showerror("错误", "宽度必须为正数")
                return
                
            if height is not None and height <= 0:
                messagebox.showerror("错误", "高度必须为正数")
                return
                
        except ValueError:
            messagebox.showerror("错误", "请输入有效的尺寸数字")
            return
        
        quality = self.quality_var.get()
        
        try:
            self.status_var.set("正在处理图片...")
            self.root.update()  # 更新界面显示
            
            # 打开图片
            with Image.open(input_path) as img:
                original_width, original_height = img.size
                
                # 计算调整后的尺寸
                if width is not None and height is None:
                    ratio = width / original_width
                    height = int(original_height * ratio)
                elif width is None and height is not None:
                    ratio = height / original_height
                    width = int(original_width * ratio)
                
                # 调整图片大小
                resized_img = img.resize((width, height), Image.Resampling.LANCZOS)
                
                # 保存图片
                file_ext = output_path.lower().split('.')[-1]
                if file_ext in ['jpg', 'jpeg']:
                    resized_img.save(output_path, 'JPEG', quality=quality, optimize=True)
                elif file_ext == 'png':
                    compress_level = 9 - int(quality / 10)
                    resized_img.save(output_path, 'PNG', compress_level=compress_level)
                else:
                    resized_img.save(output_path, optimize=True)
                
                # 计算文件大小变化
                original_size = os.path.getsize(input_path)
                new_size = os.path.getsize(output_path)
                size_reduction = (1 - new_size / original_size) * 100
                
                # 显示结果 - 确保所有信息都能显示
                result = (f"处理成功!\n\n"
                          f"原始尺寸: {original_width}x{original_height} 像素\n"
                          f"调整后尺寸: {width}x{height} 像素\n\n"
                          f"原始大小: {original_size / 1024:.2f} KB\n"
                          f"新大小: {new_size / 1024:.2f} KB\n"
                          f"大小减少: {size_reduction:.2f}%")
                
                self.result_text.config(state=tk.NORMAL)
                self.result_text.delete(1.0, tk.END)
                self.result_text.insert(tk.END, result)
                self.result_text.config(state=tk.DISABLED)
                
                # 自动滚动到结果区域
                self.result_text.see(tk.END)
                
                self.status_var.set("处理完成")
                messagebox.showinfo("成功", "图片已成功调整大小并保存")
                
        except Exception as e:
            self.status_var.set("处理失败")
            messagebox.showerror("错误", f"处理图片时出错: {str(e)}")

if __name__ == "__main__":
    root = tk.Tk()
    app = ImageResizerApp(root)
    root.mainloop()
    